use crate::algorithms::eval_dynamic::_attractors::itgr::{Process, Scheduler};
use biodivine_lib_param_bn::biodivine_std::traits::Set;
use biodivine_lib_param_bn::symbolic_async_graph::{GraphColoredVertices, SymbolicAsyncGraph};
use biodivine_lib_param_bn::VariableId;
impl Scheduler {
pub fn new(initial: GraphColoredVertices, variables: Vec<VariableId>) -> Scheduler {
Scheduler {
active_variables: variables,
universe: initial,
processes: Vec::new(),
to_discard: None,
}
}
pub fn finalize(self) -> (GraphColoredVertices, Vec<VariableId>) {
(self.universe, self.active_variables)
}
pub fn discard_variable(&mut self, var: VariableId) {
self.active_variables
.iter()
.position(|v| *v == var)
.into_iter()
.for_each(|index| {
self.active_variables.remove(index);
});
}
pub fn discard_vertices(&mut self, set: &GraphColoredVertices) {
self.universe = self.universe.minus(set);
if let Some(to_discard) = self.to_discard.as_mut() {
*to_discard = to_discard.union(set);
} else {
self.to_discard = Some(set.clone());
}
}
pub fn spawn<P: 'static + Process>(&mut self, process: P) {
self.processes.push((process.weight(), Box::new(process)));
}
pub fn get_universe(&self) -> &GraphColoredVertices {
&self.universe
}
pub fn get_active_variables(&self) -> &[VariableId] {
&self.active_variables
}
pub fn is_done(&self) -> bool {
self.processes.is_empty()
}
pub fn step(&mut self, graph: &SymbolicAsyncGraph) {
if self.is_done() {
return;
}
if let Some(to_discard) = self.to_discard.as_ref() {
for (w, process) in self.processes.iter_mut() {
process.discard_states(to_discard);
*w = process.weight();
}
self.to_discard = None;
}
self.processes.sort_by_key(|(w, _)| usize::MAX - (*w));
if let Some((_, mut process)) = self.processes.pop() {
let is_done = process.step(self, graph);
if !is_done {
self.processes.push((process.weight(), process))
}
}
}
}